﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using PostIt.Interfaces;
using System.Diagnostics;
using System.IO;

namespace PostIt
{
    public partial class NsNoteForm : Form, IPostit
    {
        private bool _isDraging;
        private bool _isResizing;
        private int _currentX, _currenttY;

        private Point _orig;  
        private Point _diff;    
        private Point _size;

        private Color _noteBackColor;
        

        public NsNoteForm()
        {
			InitializeComponent();
			
            label1.MouseDown += new MouseEventHandler(NsNoteMouseDown);
            label1.MouseUp += new MouseEventHandler(NsNoteMouseUp);
            label1.MouseMove += new MouseEventHandler(NsNoteMouseMove);
            label1.MouseLeave += new EventHandler(NsNoteMouseLeave);
            textBox1.Visible = false;

            resizeLabel.MouseDown += new MouseEventHandler(resizeLabel_MouseDown);
            resizeLabel.MouseUp += new MouseEventHandler(resizeLabel_MouseUp);
            resizeLabel.MouseMove += new MouseEventHandler(resizeLabel_MouseMove);
        }

        void resizeLabel_MouseMove(object sender, MouseEventArgs e)
        {
            if(_isResizing)
            {
                Cursor = Cursors.SizeNWSE;
                this._diff.X = Cursor.Position.X - _orig.X;  
                this._diff.Y = Cursor.Position.Y - _orig.Y;
                
                if (_size.X + _diff.X < 50)
                    return;

                if (_size.Y + _diff.Y < 50)
                    return;

                this.Width = _size.X + _diff.X;  
                this.Height = _size.Y + _diff.Y;  

                resizeLabel.Location = new Point(this.Width - 8,this.Height - 8);
            }
        }

        void resizeLabel_MouseUp(object sender, MouseEventArgs e)
        {
            this._isResizing = false;
            Cursor = Cursors.Default;
        }

        void resizeLabel_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this._isResizing = true;                
                _orig = Cursor.Position;
                _size = new Point(Width, Height);  
            }
        }

		private Font _font;
		public override Font Font
		{
			get { return _font; }
			set
			{
				_font = value;
				this.label1.Font = value;
				this.textBox1.Font = value;
			}
		}

        private string _text;
        public override string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                label1.Text = value.Replace("\t","    ");
                textBox1.Text = value;
            }
        }

        private int _x;
        public int X
        {
            get { return _x; }
            set
            {
                _x = value;
                this.Left = value;
            }
        }

        private int _y;
        public int Y
        {
            get { return _y; }
            set
            {
                _y = value;
                this.Top = value;
            }
        }

        public Color NoteBackColor
        {
            get { return _noteBackColor; }
            set
            {
                _noteBackColor = value;
                this.label1.BackColor = value;
                this.textBox1.BackColor = value;
                this.flowLayoutPanel1.BackColor = value;
            }
        }
        
        private List<string> _attatchedFiles = new List<string>();
        public List<string> AttatchedFiles
        {
            get { return _attatchedFiles; }
        }

		/// <summary>
		/// Used to hide the Note from the "alt-tab"
		/// </summary>
		protected override CreateParams CreateParams
		{
			get
			{
				CreateParams cp = base.CreateParams;
				// turn on WS_EX_TOOLWINDOW style bit
				cp.ExStyle |= 0x80;
				return cp;
			}
		}

        void NsNoteMouseMove(object sender, MouseEventArgs e)
        {
            if (_isDraging)
            {
                X = Left + (e.X - _currentX);
                Y = Top + (e.Y - _currenttY);

                Refresh();
                Cursor = Cursors.SizeAll;
                BringToFront();
            }
        }

        void NsNoteMouseLeave(object sender, EventArgs e)
        {
            this._isDraging = false;
        }

        void NsNoteMouseUp(object sender, MouseEventArgs e)
        {
            this._isDraging = false;
            Cursor = Cursors.Default;
        }

        void NsNoteMouseDown(object sender, MouseEventArgs e)
        {
            this.BringToFront();
            if (e.Button == MouseButtons.Left)
            {
                this._isDraging = true;
                _currentX = e.X;
                _currenttY = e.Y;
                Cursor = Cursors.Hand;
            }
        }

		/// <summary>
		/// Sets the color of a note
		/// </summary>
		/// <param name="c"></param>
        public void ChangeColor(Color c)
        {
            this.NoteBackColor = c;
        }

		/// <summary>
		/// Handler for the "change-color-events"
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void SetColor(object sender, EventArgs e)
		{
			Color c = ((ToolStripMenuItem)sender).BackColor;

			ChangeColor(c);
		}

		/// <summary>
		/// Toggles "always on top" on
		/// </summary>
        public void ToggleAlwaysOnTop()
        {
                this.TopMost = true;
        }

		/// <summary>
		/// Removes "always on top"
		/// </summary>
		public void ToggleAlwaysOnTopOff()
		{
			this.TopMost = false;
		}

		/// <summary>
		/// Changes the opacity of a note
		/// </summary>
		/// <param name="op"></param>
		public void ChangeOpacity(double op)
		{
			this.Opacity = op;
		}

		/// <summary>
		/// Enables the "edit-mode" of a note
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        private void textBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Text = textBox1.Text;
            textBox1.Visible = false;
            label1.Visible = true;
            this.Focus();
        }

		/// <summary>
		/// Disables the "edit-mode" of a note
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        private void label1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (textBox1.Visible)
            {
                textBox1.Text = label1.Text;
                textBox1.Visible = false;
            }
            else
            {
                textBox1.Visible = true;
                textBox1.Focus();
                textBox1.Select(0, 0);
                textBox1.BackColor = label1.BackColor;
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
			if (Text != "" || _attatchedFiles.Count > 0)
			{
				DialogResult res = MessageBox.Show(AppResources.ConfirmDeleteNote, AppResources.ConfirmDeleteNoteCaption, MessageBoxButtons.YesNo);
				if (res == DialogResult.Yes)
					Dispose();
			}
			else
				this.Dispose();
        }

		/// <summary>
		/// Makes a simple search of the note.
		/// </summary>
		/// <param name="s"></param>
		/// <returns></returns>
		public bool Search(string s)
		{
			return this.Text.ToLower().Contains(s.ToLower());
		}

		/// <summary>
		/// Hides (fades out) the note
		/// </summary>
		public void HidePostIt()
		{
			this.Opacity = 0.3f;
		}

		/// <summary>
		/// Shows the note
		/// </summary>
		public void ShowPostIt()
		{
			this.Opacity = 1f;            
		}

        /// <summary>
        /// Sets the position of the note on the screen
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void SetScreenPos(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        private void NsNoteForm_Resize(object sender, EventArgs e)
        {
            Size s = this.Size;
            s.Height -= 3;
            s.Width -= 3;
            this.label1.Size = s;
            this.label2.Size = s;
            this.textBox1.Size = s;
            resizeLabel.Location = new Point(this.Width - 8, this.Height - 8);
            flowLayoutPanel1.Location = new Point(3,this.Height - 24);            
        }

        public void ChangeFont(Font font)
        {
            if(font != null)
                this.Font = font;
        }

        public override string ToString()
        {
            return this.Text;
        }
        
        /// <summary>
        /// Attatches files (links to files) to a note
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItemAttatchFiles_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;
            List<string> filesToAdd = new List<string>();
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                foreach (var file in dialog.FileNames)
                {
                        filesToAdd.Add(file);
                }

                if (filesToAdd.Count > 0)
                    AddAttatchments(filesToAdd);
            }
        }

        public void AddAttatchments(List<string> filesToAdd)
        {
            foreach (var file in filesToAdd)
            {
                if (!_attatchedFiles.Contains(file))
                {
                    _attatchedFiles.Add(file);

                    PictureBox pb = new PictureBox();
                    pb.Image = AppResources.attatchedfile;
                    pb.Location = new Point(3, this.Height - 20);
                    pb.Size = new Size(12, 15);
                    pb.MouseDoubleClick += new MouseEventHandler(pb_MouseDoubleClick);
                    ToolTip tp = new ToolTip();
                    tp.SetToolTip(pb, file);
                    pb.Tag = file;
                    pb.BringToFront();                   
                    flowLayoutPanel1.Controls.Add(pb);
                }
            }
        }

        void pb_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            
            if(e.Button != MouseButtons.Left)
                return;

            PictureBox pb = ((PictureBox) sender);            
            Process process = new Process();

            if(!File.Exists(pb.Tag.ToString()))
            {
                return;   // TODO: remove the picturebox             
            }

            

            process.StartInfo.FileName = pb.Tag.ToString();            
            process.Start();
            process.Dispose();
        }

        private void label1_DragEnter(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.All;
            else
                e.Effect = DragDropEffects.None;
        }

        private void label1_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[]) e.Data.GetData(DataFormats.FileDrop, false);
            List<string> filesToAttatch = new List<string>();
            

            for(int i = 0; i < files.Length; i++)
            {
                filesToAttatch.Add(files[i]);
            }

            if(filesToAttatch.Count > 0)
                AddAttatchments(filesToAttatch);
        }

        private void resizeLabel_MouseEnter(object sender, EventArgs e)
        {
            this.Cursor = Cursors.SizeNWSE;
        }

        private void resizeLabel_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        }
    }
}
